home *** CD-ROM | disk | FTP | other *** search
/ LOGIC Apps / Logic-APPLE_II_APPS.iso / mac / LOGIC Apple II 5.25" Library - ProDOS / PRO045.dsk / INSTR.816OPS.txt < prev    next >
Text File  |  2012-02-16  |  16KB  |  378 lines

  1.  
  2. from:      Brian Fitzgerald
  3.            HAL Labs
  4.            18942 Dallas
  5.            Perris, CA 92370
  6.  
  7. (c) 1987 HAL Labs
  8. This document may be freely distributed as long as this copyright notice
  9. goes with it!
  10.  
  11. The Surgeon General has not determined that the following material is dangerous
  12. to your health.  However...
  13.  
  14.  
  15.  
  16.  
  17. Chapter 4:  65816 instructions and LISA syntax
  18.  
  19.  
  20.  
  21. A difference in syntax.
  22.  
  23. The accepted definition of 65816 instruction addressing modes is a bit awkward.
  24. There are a few differences between what some users may be accustomed to as
  25. regards the syntax of some instructions,  and the way that LISA does things.
  26.  
  27. When the 6502 was designed, it was as a 8-bit processor; all the instructions
  28. work with 8-bit data through the registers (A,X and Y) and 8-bit (zero page
  29. and stack) and 16-bit (absolute) addresses.  Since data size was smaller than
  30. address size (for absolute addresses), addresses had to be manipulated in two
  31. parts,  low byte and high byte.  So,  if you had to initialize a zero page
  32. pointer to some immediate-value address,  there had to be some way to tell the
  33. assembler to use the low and high order bytes of an address.  In LISA, you would
  34. use:
  35.  
  36. SCREEN   equ $2000        ;start of //e hi-res screen
  37. SCINIT   lda #SCREEN      ;get low byte of address
  38.          sta PTR
  39.          lda /SCREEN      ;get high byte of address
  40.          sta PTR+1
  41.  
  42.  
  43. So, here we use the '#' pound sign to specify the low byte of an immediate
  44. value, and the '/' slash sign to specify the high byte of an immediate value.
  45. (Some assemblers use #< and #> for low and high bytes).
  46. Okay,  so no problem,  right?
  47.  
  48. Well, after a while (about 1981), 16-bit processors started to become very
  49. popular, and certain people started thinking about a 16-bit version of the 6502.
  50. So,  now we have the 65816.  The 65816 is unusual in that it directly executes
  51. the older 6502 programs directly,  with no translation; and yet it is also a
  52. 16-bit part.  It handles this "split-personality" with the aid of several
  53. internal flags that the programmer can manipulate.  If the M
  54. (for memory/accumulator) flag is set (M=1) then the accumulator (and all memory
  55. fetch/stores) are 8-bit; if it is cleared (M=0) then we have a 16-bit
  56. accumulator.
  57.  
  58. This can be confusing!!  There are actually no 8 or 16-bit instructions per se;
  59. if you are in 16-bit mode, all the appropriate instructions are 16-bit.  So,
  60. for example:
  61.  
  62.          sep #%00100000      ;set for 8-bit memory/acc
  63.          lda #$1234          ;load 1-byte value #$34
  64.          rep #%00100000      ;set for 16-bit memory/acc
  65.          lda #$1234          ;load 2-byte value #$1234
  66.  
  67. The first line sets 8-bit memory/accumulator mode; therefore, the next LDA
  68. instruction will load a 1-byte value into the accumulator.  The third line
  69. sets 16-bit memory/accumulator mode; therefore, the last LDA instruction will
  70. load a 2-byte value into the accumulator.  But, if you looked at the opcodes
  71. generated, both LDAs are the same!  The 65816 chip knows what is 8-bit and what
  72. is 16-bit because it looks at the flags; but you have to remember.
  73.  
  74. Finally,  the point of this; when you are writing code, you would like to be
  75. able to look at a line of source code and say "Yes, I meant this to be 8-bit
  76. (or 16-bit) blah blah blah".  So, we need some further identifiers; and this
  77. is where LISA really diverges from the standard.  For 8-bit data we use:
  78.  
  79.          lda #$123456        ;get low byte $56
  80.          lda /$123456        ;get mid byte $34
  81.          lda ^$123456        ;get bank byte $12
  82.  
  83. for 8-bit immediate data and
  84.  
  85.          lda |$123456        ;get low word $3456
  86.          lda \$123456        ;get high word $0012
  87.  
  88. for 16-bit immediate data.  The standard would have you use the exact same
  89. modifiers for both 8-bit and 16-bit mode!  Further, you have to go
  90. through contortions to tell the assembler that you are in 8-bit or 16-bit mode.
  91. This would not be that bad, except that you can't just stay in 16-bit mode;
  92. if you want to do 8-bit manipulations (say, on character data), you have to
  93. go to 8-bit mode.
  94.  
  95. According to programmers at Apple, 80% of their problems involved being in the
  96. wrong mode!
  97.  
  98. Now, if you like that sort of thing (or if you are translating code from APW,
  99. for example), you can use semi-standard mnemonics, in that '#' and '^' will
  100. behave differently in 8-bit or 16-bit mode.  You have to tell the assembler
  101. what mode(s) with new pseudo-ops:
  102.  
  103.          .sa          ;set 8-bit memory/accumulator
  104.          .la          ;set 16-bit memory/accumulator
  105.          .sx          ;set 8-bit index registers
  106.          .lx          ;set 16-bit index registers
  107.  
  108. You must also do the appropriate REP or SEP at the same time, because the .SA,
  109. .LA, .SX, and .LX pseudo-ops are instructions for the assembler only; if you
  110. do one without the other, your program will fail spectacularly when it reaches
  111. that point in execution.  It was mainly for this reason that LISA diverged from
  112. the standard as far as it did (also, the standard is very wordy).
  113. As an example, you could do this, if you really wanted to:
  114.  
  115. M        =    %00100000     ;memory/ACC bit
  116. X        =    %00010000     ;index registers bit
  117. TEST     sep  #M+X          ;set for 8-bit ACC, index
  118.          .sa                ;tell LISA about short ACC
  119.          .sx                ;and short index
  120.          lda  #$23          ;get a byte
  121.          sta  ONEBYTE       ;save a byte
  122.          rep  #M            ;set for 16-bit ACC
  123.          .la                ;and long ACC now
  124.          lda  #$23          ;get a word (#$0023)
  125.          sta  TWOBYTE       ;save a word
  126.   
  127. It looks straightforward here, but gets confusing in a 1,000 line program.
  128. Also, there's a lot more typing to do to keep things straight.
  129.  
  130. So, what are the differences between LISA and the so-called standard?  First,
  131. there are various byte and word select operators for immediate values and
  132. constants.
  133.  
  134.  8-bit
  135.      LISA        Standard          Operation         result
  136.  
  137.   #$01020304    #$01020304       select low byte      04
  138.                     or
  139.                 #<$01020304
  140.  
  141.   /$01020304    #>$01020304      select middle byte   03
  142.  
  143.   ^$01020304    #^$01020304      select high byte     02
  144.  
  145.  
  146.  16-bit
  147.      LISA        Standard          Operation         result
  148.  
  149.   |$01020304    #$01020304       select low word      0304
  150.       or           or
  151.   #$01020304    #<$01020304
  152.  
  153.   \$01020304    #^$01020304      select high word     0102
  154.       or
  155.   ^$01020304
  156.  
  157.  
  158.  
  159. Further,  LISA handles labels a little differently as well.  In the 6502, there
  160. were two different kinds of addresses P zero page and absolute.  In the 65816,
  161. there are three kinds P direct page (similar to zero page), absolute, and long.
  162. The standard is to let the size of the address tell the type, so that addresses
  163. from 0I255 are direct page, addresses from 256I65535 are absolute, and the rest
  164. (65536I16777215) are long.  LISA, on the other hand, uses explicit declarators
  165. to set direct page, absolute, and long.
  166.  
  167.      LISA               Standard                 Operation
  168.  
  169.  LABEL epz $23        LABEL equ $23          define direct-page label
  170.  LABEL equ $1234      LABEL equ $1234        define absolute label
  171.  LABEL eql $123456    LABEL equ $123456      define long label
  172.  
  173. LISA has different equates for two reasons; 1) it is more precise, and 2) it
  174. handles conflicts with low-valued absolute and long addresses.  This was not
  175. as much a problem with the 6502 as it is with the 65816, with it's multiple
  176. banks of 64K blocks (via the data and program bank registers) and moveable
  177. direct page.  Consider the following:
  178.  
  179.          org   $010000           ;start at bank $01, addr $0000
  180. CODE     lda   #$02              ;set DBR to bank $02
  181.          pha
  182.          plb                     ;stack value to DBR
  183.          lda   DATA
  184.          rts
  185. DATA     byt   5
  186.  
  187. DATA is in the same bank as CODE, so any reasonable assembler would say "Ah HA!
  188. Same bank, so use absolute".  Unfortunately, we set the DBR (data bank register)
  189. to a different bank, so we end up fetching data from $02xxxx instead of $01xxxx.
  190. This is where several LISA pseudo-ops come into play.
  191.  
  192. First, there is the FAR pseudo-op.  If FAR is used on any label, it will 
  193. automatically be given the LONG attribute, and any instructions referencing
  194. that will use long addressing modes.  This way, you could do equates into
  195. bank 0 that were long easily, without having to do type coercion for every
  196. single reference (as the standard would have you do).  For the case above,
  197. we could have added:
  198.  
  199.         far DATA                ;declare DATA as long always
  200.  
  201. after the first line, and that would have made all references to DATA as long.
  202.  
  203. This is fine sometimes (and usually necessary if you're working with banks given
  204. you by the IIGS memory manager), but what if you know what banks you're in at
  205. certain times, and want to optimize some fetches that would be in the same bank.
  206. Example
  207.  
  208.         org   $010000            ;start at bank $01, addr $0000
  209.         far   DATA               ;declare DATA as long always
  210.         far   DATA2              ;declare DATA2 as long always
  211. CODE    lda   #$02               ;set DBR to bank $02
  212.         pha
  213.         plb                      ;stack value to DBR
  214.         lda   DATA               ;will be LONG ref
  215.         sta   DATA2              ;will be LONG ref
  216.         rts
  217. DATA    byt   5
  218.         org   $020000            ;in bank $02
  219. DATA2   byt   12
  220.  
  221. Now, here we are loading from $01xxxx and saving at $02xxxx; but we know that
  222. the DBR is pointing at bank $02, and DATA2 is needlessly long.  We could have
  223. not defined DATA2 as FAR, but then later we might have moved the DBR again and
  224. still want to have referenced DATA2 again.  What to do?
  225.  
  226. To fix this, we introduce a new pseudo ops; .DB.  The action of this is to
  227. inform the assembler (if we know) what the value of the DBR register is.  So,
  228. looking at our example again, we could do the following:
  229.  
  230.         org   $010000             ;start at bank $01, addr $0000
  231. CODE    lda   #$02                ;set DBR to bank $02
  232.         pha
  233.         plb                       ;stack value to DBR
  234.         .db   $020000             ;tell LISA we're in bank $02
  235.         lda   DATA                ;will be LONG ref
  236.         sta   DATA2               ;will be ABS ref
  237.         lda   #$01                ;set DBR to bank $01
  238.         pha
  239.         plb                       ;stack value to DBR
  240.         .db   $010000             ;tell LISA we're in bank $02
  241.         lda   DATA                ;will be ABS ref
  242.         sta   DATA2               ;will be LONG ref
  243.         rts
  244. DATA    byt 5
  245.         org $020000               ;in bank $02
  246. DATA2 byt 12
  247.  
  248. Now, as you can see from reading the comments, LISA will keep track of the
  249. different segments, and generate ABSOLUTE or LONG instructions in context.
  250. Effective use of the .DB pseudo-op can save you lots of trouble.  NOTE:  the
  251. .DB instruction expects a long address, of which it uses the high-order byte
  252. only.  This is so that you can use a label in the bank you're targeting with
  253. the .DB instruction; also, so that you can use the value of the PC counter,
  254. i.e. ".DBJ*", which would reset LISA's notion of where the DBR is to the
  255. current value of the PBR (program bank register).
  256.  
  257. One useful trick when setting the DBR to point to a bank returned by the
  258. memory manager is to use .DB to tell LISA that you are in a bank which will
  259. never be referenced normally, like bank $FF (which contains sancrosanct ROM
  260. code on the IIGS).  I.e.
  261.  
  262.         lda   SymBank                ;set DBR to symbol table bank
  263.         pha
  264.         plb                          ;stack value to DBR
  265.         plb
  266.         .db   $FF0000                ;tell LISA we're in bank $FF
  267.         lda (Sym)                    ;get symbol byte
  268.         sta DATA                     ;and save it
  269.  
  270. where here we load ABSOLUTE from a bank that we don't know the location of at
  271. assembly timeP so we tell LISA it's at a location we will never access normally.
  272. Note that you could NOT say ".DBJSYMBANK" because SYMBANK is a variable, not an
  273. assembly-time constant.
  274.  
  275. Finally, there are every once in a while situations that don't fall into any
  276. of the above catagories, where you want to have some reference be ABSOLUTE or
  277. LONG where there is no way to tell the assembler other than by type coercion.
  278. Since there are already so many prefix characters for an expression (byte, word,
  279. negation etc), LISA prefers to use a suffix on the label P this also makes more
  280. sense, since you are coercing the label, not the expression (although the
  281. expression usually follows as a consequence).  To do type coercion, you follow
  282. the label with a suffix like ":A" for ABSOLUTE and ":L" for LONG.  So, we could
  283. do
  284.  
  285.         lda   SymBank                 ;set DBR to symbol table bank
  286.         pha
  287.         plb                           ;stack value to DBR
  288.         plb
  289.         lda   BYTES:A                 ;absolute ref
  290.         sta   DATA                    ;and save it
  291.  
  292. if we knew that DATA was an offset from the start of the bank, say if we had
  293. allocated a whole 64K bank and were using absolute offsets into that bank
  294. (which can be a handy thing to do at times).
  295.  
  296.  
  297. So there are some more differences to categorize between LISA and the standard
  298. 65816 syntax.  They are.
  299.  
  300.  
  301.      LISA                    Standard                 Operation
  302.  
  303.  (not applicable)             >Label                force direct page
  304.    Label:A                    |Label                force absolute
  305.    Label:L                    <Label                force long
  306.  
  307.  _______________________________________________________________________
  308.  
  309.  Label epz $23               Label equ $23          force direct page
  310.        lda Label                  lda <Label
  311.  
  312.  LISA needs no coercion     Labels are rarely (if ever)
  313.  because the label is       coerced like this anyway.
  314.  defined as direct page.
  315.  _______________________________________________________________________
  316.  
  317.  Label equ $23               Label equ $23          force absolute
  318.        lda Label                   lda |Label
  319.  
  320.  LISA needs no coercion         This is needed to force
  321.  because the label is           absolute for low addresses.
  322.  defined as absolute.
  323.  
  324.  Label byt "a String"
  325.        lda Label:A,X
  326.  
  327.  LISA can coerce labels if
  328.  it has to, though.
  329.  
  330.  _______________________________________________________________________
  331.  
  332.  Label eql $2305             Label equ $23           force long
  333.        lda Label                  lda >Label
  334.  
  335.  LISA needs no coercion       This is needed to force
  336.  because the label is         long for low addresses.
  337.  defined as long.
  338.  
  339.  Label byt "a String"
  340.        lda Label:L,X
  341.         
  342.  LISA can coerce labels if
  343.  it hasto, though.
  344.  
  345.  _______________________________________________________________________
  346.  
  347.  
  348. Postscript:
  349.  
  350. As you may have inferred, this is taken from the manual for the LISA816
  351. assembler.
  352.  
  353. I have translated it to text and downloaded it for a specific reason:
  354. evangelization.  There are some quirky things about the "standard" way of
  355. doing things that I disagree with; some decisions were made without being
  356. thought through.  This is my opinion, of course.  If you have rational
  357. comments or objections, I would be more than delighted to hear from you.  I
  358. may be contacted on
  359.  
  360.     GEnie:      HAL.LABS
  361.     Delphi      HALLABS
  362.     CompuServe: 72250,3226
  363.  
  364. or (through the vagaries of the US mail)
  365.  
  366.     HAL Labs
  367.     18942 Dallas
  368.     Perris, CA 92370
  369.  
  370. Address comments to Brian Fitzgerald.
  371.  
  372. The LISA 816 assembler package is currently at version 4.0g, and may be
  373. purchased from the above address for $50.00.  It currently runs in emulation
  374. mode, but generates OMF files (as well as BIN etc) that can be run in native
  375. mode.  Native-mode LISA is scheduled for a Xmas release, and will be $75.00
  376. (or a $25.00 upgrade from 4.0).  LISA816 boasts 100,000 lines per minute
  377. assembly, interactive syntax-checking editor, fully panoply of data-declaration
  378.